﻿using System;

namespace Kyoh.Lib.Excel
{
    /// <summary>ワークシートを表します。</summary>
	public class Worksheet : Component
	{
		private Worksheet(object exWorksheet, Component parent)
			: base(exWorksheet, parent)
		{
		}

        /// <summary>Excel COM オブジェクトで、新しいインスタンスを初期化します。</summary>
        /// <param name="obj">Excel COM オブジェクト</param>
        /// <param name="parent">親となる <see cref="Component"/> オブジェクト。</param>
		internal static Worksheet Create(object obj, Component parent)
		{
			return obj == null ? null : new Worksheet(obj, parent);
		}

        /// <summary>ワークシートをアクティブにします。</summary>
		public void Activate()
		{
			base.InvokeMethod("Activate");
		}

        /// <summary>数式をすべて計算します。</summary>
		public void Calculate()
		{
			base.InvokeMethod("Calculate");
		}

        /// <summary>セルを取得します。</summary>
        public Range Cells
        {
            get { return Range.Create(base.GetProperty("Cells"), this); }
        }

        /// <summary>列を取得します。</summary>
        public Range Columns
        {
            get { return Range.Create(base.GetProperty("Columns"), this); }
        }

        /// <summary>行を取得します。</summary>
        public Range Rows
        {
            get { return Range.Create(base.GetProperty("Rows"), this); }
        }

        /// <summary>入力規則に違反しているセルをマークします。</summary>
		public void CircleInvalid()
		{
			base.InvokeMethod("CircleInvalid");
		}

        /// <summary>入力規則に違反したセルのマークを消去します。</summary>
		public void ClearCircles()
		{
			base.InvokeMethod("ClearCircles");
		}

        /// <summary>ワークシートをコピーします。</summary>
        /// <param name="Before">コピー先のシート。指定したシートの1つ前にコピーされます。</param>
        /// <param name="After">コピー先のシート。指定したシートの後にコピーされます。</param>
		public void Copy(Worksheet Before = null, Worksheet After = null)
		{
			switch ((Before != null ? 1 : 0) | (After != null ? 2 : 0))
			{
				case 1:
					base.InvokeMethod("Copy", Before.ExcelComObject);
					break;

				case 2:
					base.InvokeMethod("Copy", Type.Missing, After.ExcelComObject);
					break;

				default:
					throw new ArgumentNullException("Before, Afterが共にnullか、未指定です。");
			}
		}

        /// <summary>ワークシートを削除します。</summary>
		public void Delete()
		{
			base.InvokeMethod("Delete");
		}

        /// <summary>使用されているセルの先頭列を取得します。</summary>
		public int FirstColumn
		{
			get { return this.UsedRange.Column; }
		}

        /// <summary>使用されているセルの先頭行を取得します。</summary>
		public int FirstRow
		{
			get { return this.UsedRange.Row; }
		}

        /// <summary>水平方向の改行位置を取得します。</summary>
		public HPageBreaks HPageBreaks
		{
			get { return HPageBreaks.Create(base.GetProperty("HPageBreaks"), this); }
		}

        /// <summary>インデックスを取得します。</summary>
		public int Index
		{
			get { return (int)base.GetProperty("Index"); }
		}

        /// <summary>使用されているセルの最終列を取得します。</summary>
		public int LastColumn
		{
			get
			{
				var columns = this.UsedRange.Columns;
				return columns.Column + columns.Count - 1;
			}
		}

        /// <summary>使用されているセルの最終行を取得します。</summary>
		public int LastRow
		{
			get
			{
				var rows = this.UsedRange.Rows;
				return rows.Row + rows.Count - 1;
			}
		}

        /// <summary>シートを移動します。</summary>
        /// <param name="Before">移動先のシート。指定したシートの1つ前に移動されます。</param>
        /// <param name="After">移動先のシート。指定したシートの後に移動されます。</param>
		public void Move(Worksheet Before = null, Worksheet After = null)
		{
			switch ((Before != null ? 1 : 0) | (After != null ? 2 : 0))
			{
				case 1:
					base.InvokeMethod("Move", Before.ExcelComObject);
					break;

				case 2:
					base.InvokeMethod("Move", Type.Missing, After.ExcelComObject);
					break;

				default:
					throw new ArgumentNullException("Before, Afterが共にnullか、未指定です。");
			}
		}

        /// <summary>シート名を取得・設定します。</summary>
		public string Name
		{
			get { return (string)base.GetProperty("Name"); }
			set { base.SetProperty("Name", value); }
		}

        /// <summary>ページ設定を取得します。</summary>
		public PageSetup PageSetup
		{
			get { return PageSetup.Create(base.GetProperty("PageSetup"), this); }
		}

        /// <summary>クリップボードの中身を指定セルに貼り付けます。</summary>
        /// <param name="destination">貼り付けるセル。</param>
		public void Paste(Range destination)
		{
			base.InvokeMethod("Paste", destination.ExcelComObject, Type.Missing);
		}

        /// <summary>形式を指定してクリップボードを貼り付けます。</summary>
        /// <param name="Format">形式を表す文字列。</param>
        /// <param name="Link">リンクとして貼り付ける。</param>
        /// <param name="DisplayAsIcon">アイコンで表示。</param>
        /// <param name="IconFileName">アイコンファイル名。</param>
        /// <param name="IconIndex">アイコンインデックス。</param>
        /// <param name="IconLabel">アイコンに表示するラベル文字列。</param>
        /// <param name="NoHTMLFormatting">HTML書式を無視。</param>
        public void PasteSpecial(string Format = null, bool? Link = null, bool? DisplayAsIcon = null, string IconFileName = null, int? IconIndex = null, string IconLabel = null, bool? NoHTMLFormatting = null)
        {
            base.InvokeMethod("PasteSpecial",
                Format ?? Type.Missing,
                Link ?? Type.Missing,
                DisplayAsIcon ?? Type.Missing,
                IconFileName ?? Type.Missing,
                IconIndex ?? Type.Missing,
                IconLabel ?? Type.Missing,
                NoHTMLFormatting ?? Type.Missing);
        }

        /// <summary>前のシートを取得します。</summary>
		public Worksheet Previous
		{
			get
			{
				object obj = base.GetProperty("Previous");
				return (obj == null) ? null : new Worksheet(obj, this);
			}
		}

        /// <summary>シートを保護します。</summary>
        /// <param name="Password">パスワード。</param>
        /// <param name="DrawingObjects">図形を保護する場合は <c>true</c> 。既定値は <c>false</c> 。</param>
        /// <param name="Contents">ロックされたセルの内容を保護する場合は <c>true</c> 。規定値は <c>false</c> 。</param>
        /// <param name="Scenarios">シナリオを保護する場合は <c>true</c> 。規定値は <c>false</c> 。</param>
        /// <param name="UserInterfaceOnly">ユーザー インターフェイスを保護し、マクロを保護しない場合は <c>true</c> 。規定値は <c>false</c> 。</param>
        /// <param name="AllowFormattingCells">ロックされているセルの書式設定を許可する場合は <c>true</c> 。規定値は <c>false</c> 。</param>
        /// <param name="AllowFormattingColumns">ロックされている列の書式設定を許可する場合は <c>true</c> 。規定値は <c>false</c> 。</param>
        /// <param name="AllowFormattingRows">ロックされている行の書式設定を許可する場合は <c>true</c> 。規定値は <c>false</c> 。</param>
        /// <param name="AllowInsertingColumns">列の挿入を許可する場合は <c>true</c> 。規定値は <c>false</c> 。</param>
        /// <param name="AllowInsertingRows">行の挿入を許可する場合は <c>true</c> 。規定値は <c>false</c> 。</param>
        /// <param name="AllowInsertingHyperlinks">ハイパーリンクの挿入を許可する場合は <c>true</c> 。規定値は <c>false</c> 。</param>
        /// <param name="AllowDeletingColumns">列の削除を許可する場合は <c>true</c> 。規定値は <c>false</c> 。</param>
        /// <param name="AllowDeletingRows">行の削除を許可する場合は <c>true</c> 。規定値は <c>false</c> 。</param>
        /// <param name="AllowSorting">シートの並び替えを許可する場合は <c>true</c> 。規定値は <c>false</c> 。</param>
        /// <param name="AllowFiltering">オートフィルタの利用を許可する場合は <c>true</c> 。規定値は <c>false</c> 。</param>
        /// <param name="AllowUsingPivotTables">ピボットテーブルの利用を許可する場合は <c>true</c> 。規定値は <c>false</c> 。</param>
        public void Protect(
            string Password = null,
            bool? DrawingObjects = null,
            bool? Contents = null,
            bool? Scenarios = null,
            bool? UserInterfaceOnly = null,
            bool? AllowFormattingCells = null,
            bool? AllowFormattingColumns = null,
            bool? AllowFormattingRows = null,
            bool? AllowInsertingColumns = null,
            bool? AllowInsertingRows = null,
            bool? AllowInsertingHyperlinks = null,
            bool? AllowDeletingColumns = null,
            bool? AllowDeletingRows = null,
            bool? AllowSorting = null,
            bool? AllowFiltering = null,
            bool? AllowUsingPivotTables = null)
        {
            base.InvokeMethod("Protect",
                Password ?? Type.Missing,
                DrawingObjects ?? Type.Missing,
                Contents ?? Type.Missing,
                Scenarios ?? Type.Missing,
                UserInterfaceOnly ?? Type.Missing,
                AllowFormattingCells ?? Type.Missing,
                AllowFormattingColumns ?? Type.Missing,
                AllowFormattingRows ?? Type.Missing,
                AllowInsertingColumns ?? Type.Missing,
                AllowInsertingRows ?? Type.Missing,
                AllowInsertingHyperlinks ?? Type.Missing,
                AllowDeletingColumns ?? Type.Missing,
                AllowDeletingRows ?? Type.Missing,
                AllowSorting ?? Type.Missing,
                AllowFiltering ?? Type.Missing,
                AllowUsingPivotTables ?? Type.Missing);
        }

        /// <summary>セルを取得します。</summary>
		public Range Range
		{
			get { return this.Cells; }
		}

        /// <summary>インデックスを指定してセルを取得します。戻り値は、取得できたかどうかです。</summary>
        /// <param name="index">セルのインデックス。</param>
        /// <param name="range">セルが取得できた場合の出力パラメータ。</param>
        /// <returns>セルを取得できた場合は <c>true</c> 。できなかった場合は <c>false</c> 。</returns>
        public bool TryGetRange(string index, out Range range)
        {
            return this.Range.TryGetRange(index, out range);
        }

        /// <summary>すべての改ページを消去します。</summary>
		public void ResetAllPageBreaks()
		{
			base.InvokeMethod("ResetAllPageBreaks");
		}

        /// <summary>スクロール位置を取得・設定します。</summary>
		public string ScrollArea
		{
			get { return base.GetProperty("ScrollArea") as string; }
			set { base.SetProperty("ScrollArea", value); }
		}

        /// <summary>シートを選択します。</summary>
        /// <param name="replace">既に選択されているシートの選択を解除する場合は <c>true</c> 。規定値は <c>false</c> 。</param>
		public void Select(bool replace = false)
		{
			base.InvokeMethod("Select", replace);
		}

        /// <summary>背景画像を設定します。</summary>
        /// <param name="filename">背景画像のファイル名。</param>
		public void SetBackgroundPicture(string filename)
		{
			base.InvokeMethod("SetBackgroundPicture", filename);
		}
        
        /// <summary>すべてのセルを表示します。</summary>
		public void ShowAllData()
		{
			base.InvokeMethod("ShowAllData");
		}
        
        /// <summary>シートのタブを表す <see cref="Tab"/> オブジェクトを取得します。</summary>
		public Tab Tab { get { return Tab.Create(base.GetProperty("Tab"), this); } }

        /// <summary>シートの保護を解除します。</summary>
        /// <param name="password">パスワード。</param>
		public void Unprotect(string password = null)
		{
			base.InvokeMethod("Unprotect", password == null ? Type.Missing : password);
		}

        /// <summary>使用されているセルを取得します。</summary>
		public Range UsedRange
		{
			get { return Range.Create(base.GetProperty("UsedRange"), this); }
		}

        /// <summary>シートの表示状態を取得・設定します。</summary>
		public SheetVisibility Visiblity
		{
			get { return (SheetVisibility)(int)base.GetProperty("Visible"); }
			set { base.SetProperty("Visible", (int)value); }
		}

        /// <summary>垂直方向の改ページを取得します。</summary>
		public VPageBreaks VPageBreaks
		{
			get { return VPageBreaks.Create(base.GetProperty("VPageBreaks"), this); }
		}

	}
}
